using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;


public class VisualObjectController : MonoBehaviour
{
    float m_rotateValue;
    
    Vector3 m_lastCenter, m_lastDirection;
    
    bool m_leftHandHold = false, m_rightHandHold = false;
    bool m_leftHandTrigger = false, m_rightHandTrigger = false;
    bool m_leftHandTriggerPerformed = false, m_rightHandTriggerPerformed = false;

    [SerializeField] InputActionAsset inputActionAsset;
    [SerializeField] Transform originTransform;
    [SerializeField] Transform leftHandTransform;
    [SerializeField] Transform rightHandTransform;

    [SerializeField] UnityEvent resetStart;
    [SerializeField] UnityEvent resetDone;

    [SerializeField] float rotateSpeed;
    [SerializeField] float moveSpeed;

    // Start is called before the first frame update
    void Start()
    {
        m_lastCenter = new();
        m_lastDirection = new();
        
        SetInput();
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 currentCenter = (leftHandTransform.position + rightHandTransform.position) * 0.5f;
        Vector3 currentDirection = leftHandTransform.position - rightHandTransform.position;
        
        float distance = currentDirection.magnitude;

        // calculate move (in world space)
        Vector3 deltaMove = currentCenter - m_lastCenter;
        deltaMove = Vector3.ClampMagnitude(deltaMove, 0.5f);

        // calculate rotation of direction (world space)
        var deltaRotate = Quaternion.FromToRotation(m_lastDirection, currentDirection);

        if (m_leftHandHold && m_rightHandHold)
        {
            // move 
            transform.position = deltaMove * moveSpeed + transform.position;
            
            // rotate (only use y-axis component of rotation)
            transform.Rotate(new Vector3(0f, deltaRotate.eulerAngles.y, 0f));
            
            // scale
            transform.localScale = transform.localScale * distance / m_lastDirection.magnitude;
        }

        m_lastCenter = currentCenter;
        m_lastDirection = currentDirection;


    }

    private void ResetTransform()
    {
        transform.position = originTransform.position;
        transform.rotation = originTransform.rotation;
        transform.localScale = originTransform.localScale;
    }

    void SetInput()
    {
        var actionMap = inputActionAsset.FindActionMap("VisualAnalysis");
        // Rotate
        var rotateAction = actionMap.FindAction("Rotate");
        rotateAction.started += context => m_rotateValue = context.ReadValue<float>();
        rotateAction.performed += context => m_rotateValue = context.ReadValue<float>();
        rotateAction.canceled += context => m_rotateValue = context.ReadValue<float>();
        rotateAction.Enable();

        // LeftHandHold
        var leftHandHoldAction = actionMap.FindAction("LeftHandHold");
        leftHandHoldAction.started += context => m_leftHandHold = context.ReadValueAsButton();
        leftHandHoldAction.performed += context => m_leftHandHold = context.ReadValueAsButton();
        leftHandHoldAction.canceled += context => m_leftHandHold = context.ReadValueAsButton();
        leftHandHoldAction.Enable();

        // RightHandHold
        var rightHandHoldAction = actionMap.FindAction("RightHandHold");
        rightHandHoldAction.started += context => m_rightHandHold = context.ReadValueAsButton();
        rightHandHoldAction.performed += context => m_rightHandHold = context.ReadValueAsButton();
        rightHandHoldAction.canceled += context => m_rightHandHold = context.ReadValueAsButton();
        rightHandHoldAction.Enable();

        // LeftHandTrigger
        var leftHandTriggerAction = actionMap.FindAction("LeftHandTriggerHold");
        leftHandTriggerAction.started += _ =>
        {
            m_leftHandTrigger = true; 
            if (m_rightHandTrigger) 
                resetStart.Invoke();
        };
        leftHandTriggerAction.performed += _ =>
        {
            m_leftHandTriggerPerformed = true;
            if (m_rightHandTriggerPerformed) 
            { 
                ResetTransform(); 
                resetDone.Invoke();
            }
        };
        leftHandTriggerAction.canceled += _ =>
        {
            m_leftHandTrigger = false;
            m_leftHandTriggerPerformed = false;
            resetDone.Invoke();
        };
        leftHandTriggerAction.Enable();

        // RightHandTrigger
        var rightHandTriggerAction = actionMap.FindAction("RightHandTriggerHold");
        rightHandTriggerAction.started += _ =>
        {
            m_rightHandTrigger = true;
            if (m_leftHandTrigger)
                resetStart.Invoke();
        };
        rightHandTriggerAction.performed += _ =>
        {
            m_rightHandTriggerPerformed = true;
            if (m_leftHandTriggerPerformed) 
            { 
                ResetTransform(); 
                resetDone.Invoke();
            }
        };
        rightHandTriggerAction.canceled += _ => 
        {
            m_rightHandTrigger = false;
            m_rightHandTriggerPerformed = false;
            resetDone.Invoke();
        };
        rightHandTriggerAction.Enable();

    }

}
